﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

using System.CodeDom;

namespace NMF.Languages.AnyText.ClassConstruction
{
    public abstract class PrimitiveType<T> : DataType
    {
        public virtual Type SystemType
        {
            get { return typeof(T); }
        }

        public override System.CodeDom.CodeTypeReference CreateTypeReference()
        {
            return new System.CodeDom.CodeTypeReference(typeof(T));
        }

        public abstract T ParseValue(string input);

        public override System.CodeDom.CodeExpression ParseValueExpression(string input)
        {
            T primitive = ParseValue(input);
            return new CodePrimitiveExpression(primitive);
        }
    }

    public class StringType : PrimitiveType<string>
    {
        public int MaxLength { get; set; }

        public override string ParseValue(string input)
        {
            if (MaxLength != null && input.Length > MaxLength) throw new ArgumentException("String is too long!");
            return input;
        }
    }

    public class RegexType : StringType
    {
        public Regex Regex { get; set; }

        public override string ParseValue(string input)
        {
            if (!Regex.IsMatch(input)) throw new ArgumentException("String does not fulfill the regular expression");
            return base.ParseValue(input);
        }
    }

    public class FloatType : PrimitiveType<double>
    {
        public double? Maximum { get; set; }
        public double? Minimum { get; set; }

        public override double ParseValue(string input)
        {
            double result = double.Parse(input);
            if (Maximum.HasValue && result > Maximum.Value) throw new ArgumentOutOfRangeException();
            if (Minimum.HasValue && result < Minimum.Value) throw new ArgumentOutOfRangeException();
            return result;
        }
    }

    public class BooleanType : PrimitiveType<bool>
    {
        public string TrueString { get; set; }
        public string FalseString { get; set; }

        public override bool ParseValue(string input)
        {
            if (TrueString == null)
            {
                return bool.Parse(input);
            }
            else
            {
                return input == TrueString;
            }
        }
    }

    public class IntegerType : PrimitiveType<long>
    {
        public long? Maximum { get; set; }
        public long? Minimum { get; set; }
    
        public override long ParseValue(string input)
        {
            long result = long.Parse(input);
            if (Maximum.HasValue && result > Maximum.Value) throw new ArgumentOutOfRangeException();
            if (Minimum.HasValue && result < Minimum.Value) throw new ArgumentOutOfRangeException();
            return result;
        }
    }

    public class DateTimeType : PrimitiveType<DateTime>
    {

        public override DateTime ParseValue(string input)
        {
            return DateTime.Parse(input);
        }
    }

    public class EnumType : DataType
    {
        private CodeTypeDeclaration declaration = new CodeTypeDeclaration();

        public EnumType()
        {
            Literals = new List<string>();
        }

        public List<string> Literals { get; set; }

        public Type SystemType
        {
            get { throw new NotImplementedException(); }
        }

        public object ParseValue(string input)
        {
            throw new NotImplementedException();
        }

        public bool IgnoreCase { get; set; }

        public override CodeExpression ParseValueExpression(string input)
        {
            throw new NotImplementedException();
        }

        public override CodeTypeReference CreateTypeReference()
        {
            return new CodeTypeReference(Name);
        }
    }
}
